package com.itheima.googleplay9.manager;

import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.util.SparseArray;
import android.util.SparseLongArray;

import com.itheima.googleplay9.api.HttpUtil;
import com.itheima.googleplay9.api.Url;
import com.itheima.googleplay9.bean.AppInfo;
import com.itheima.googleplay9.global.GooglePlayApp;
import com.itheima.googleplay9.util.Utils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * 负责管理下载的逻辑
 * Created by lxj on 2016/5/28.
 */
public class DownloadManager{
    //定义下载目录:/mnt/sdcard/包名/download
    public static final String DOWNLOAD_DIR = Environment.getExternalStorageDirectory()
            + File.separator + GooglePlayApp.context.getPackageName()
            + File.separator + "download";

    //定义6种状态常量
    public static final int STATE_NONE = 0;//没有下载的状态
    public static final int STATE_DOWNLOADING = 1;//下载中的状态
    public static final int STATE_PAUSE = 2;//暂停的状态
    public static final int STATE_FINISH = 3;//下载完成的状态
    public static final int STATE_ERROR = 4;//下载出错的状态
    public static final int STATE_WAITING = 5;//等待下载的状态，任务创建了，但是run方法没有执行

    //单例模式
    private static DownloadManager mInstance = new DownloadManager();
    public static DownloadManager getInstance(){
        return mInstance;
    }
    private DownloadManager(){
        //创建下载目录
//        if(Environment.getExternalStorageState()==Environment.MEDIA_MOUNTED){
//        }
        File dir = new File(DOWNLOAD_DIR);
        if(!dir.exists()){
            dir.mkdirs();
        }
    }
    //用来存放所有滴下载观察者对象
    private ArrayList<DownloadObserver> observerList = new ArrayList<>();
    //用来存放所有下载任务的DownloadInfo,注意:此处没有进行持久化保存
    private HashMap<Long,DownloadInfo> downloadInfoMap = new HashMap<>();

    /**
     * 下载的方法
     */
    public void download(AppInfo appInfo){
        //1.获取下载任务的DownloadInfo
        DownloadInfo downloadInfo = downloadInfoMap.get(appInfo.getId());
        if(downloadInfo==null){
            //说明是第一次下载，我们要创建DownloadInfo对象，然后放入downloadInfoMap
            downloadInfo = DownloadInfo.create(appInfo);
            downloadInfoMap.put(downloadInfo.getId(),downloadInfo);
        }

        //2.判断状态，是否可以进行下载,只有这些：none，pause，error;
        int state = downloadInfo.getState();
        if(state==STATE_NONE || state==STATE_PAUSE || state==STATE_ERROR){
            //说明可以进行下载，那么就创建下载任务，添加给线程池
            DownloadTask downloadTask = new DownloadTask(downloadInfo);

            //当下载任务创建就更改状态
            downloadInfo.setState(STATE_WAITING);
            //当状态发生改变的时候，需要通知监听器
            notifyDownloadStateChange(downloadInfo);

            //3.将下载任务添加到线程池中
            ThreadPoolManager.getInstance().execute(downloadTask);
        }
    }

    /**
     * 下载任务类
     */
    class DownloadTask implements Runnable{
        private DownloadInfo downloadInfo;
        public DownloadTask(DownloadInfo downloadInfo){
            this.downloadInfo = downloadInfo;
        }
        @Override
        public void run() {
            //4.run方法开始执行，说明下载任务要变成下载中
            downloadInfo.setState(STATE_DOWNLOADING);
            notifyDownloadStateChange(downloadInfo);

            //5.开始真正下载，请求下载文件的接口
            //下载分为2种：a.从头下载    b.断点下载
            HttpUtil.HttpResult httpResult = null;
            File file = new File(downloadInfo.getPath());
            if(!file.exists() || file.length()!=downloadInfo.getCurrentLength()){
                //需要重头下载
                file.delete();//删除无效文件
                downloadInfo.setCurrentLength(0);//清空已经下载的长度

                //请求接口下载文件
                String url = String.format(Url.Download,downloadInfo.getDownloadUrl());
                httpResult = HttpUtil.download(url);
            }else{
                //说明需要断点下载
                String url = String.format(Url.BreakDownload,downloadInfo.getDownloadUrl(),downloadInfo.getCurrentLength());
                httpResult = HttpUtil.download(url);
            }

            //6.可以读写文件了
            if(httpResult!=null && httpResult.getInputStream()!=null){
                //说明是正常的响应，那么直接进行流的读写
                InputStream is = httpResult.getInputStream();
                FileOutputStream fos = null;
                try {
                    fos = new FileOutputStream(file,true);
                    byte[] buffer = new byte[1024*15];//15k的缓冲区
                    int len = -1;
                    while ((len=is.read(buffer))!=-1 && downloadInfo.getState()==STATE_DOWNLOADING){
                        fos.write(buffer,0,len);

                        //更新currentLength
                        downloadInfo.setCurrentLength(downloadInfo.getCurrentLength()+len);
                        //通知监听器下载进度更新
                        notifyDownloadProgressChange(downloadInfo);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    //说明下载失败
                    processErrorState(file);
                }finally {
                    //关闭流和链接
                    httpResult.close();
                    try {
                         if(fos!=null){
                             fos.close();
                         }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                //7.代码走到这里，有2种情况：a.下载完成 b.暂停下载
                if(file.length()==downloadInfo.getSize() && downloadInfo.getState()==STATE_DOWNLOADING){
                    //说明下载完成了
                    downloadInfo.setState(STATE_FINISH);//更改状态为完成
                    notifyDownloadStateChange(downloadInfo);
                }else if(downloadInfo.getState()==STATE_PAUSE){
                    //已经变为暂停状态了，只需要通知监听器更新
                    notifyDownloadStateChange(downloadInfo);
                }

            }else {
                //说明下载失败
                processErrorState(file);
            }
        }

        private void processErrorState(File file) {
            file.delete();//删除失败文件
            downloadInfo.setCurrentLength(0);//清空已经下载的长度
            downloadInfo.setState(STATE_ERROR);//将状态更改为失败
            notifyDownloadStateChange(downloadInfo);
        }
    }

    /**
     * 通知监听器下载状态改变了
     */
    private void notifyDownloadStateChange(final DownloadInfo downloadInfo){
        Utils.runOnUIThread(new Runnable() {
            @Override
            public void run() {
                for(DownloadObserver observer : observerList){
                    observer.onDownloadStateChange(downloadInfo);
                }
            }
        });

    }
    /**
     * 通知监听器下载进度改变了
     */
    private void notifyDownloadProgressChange(final DownloadInfo downloadInfo){
        Utils.runOnUIThread(new Runnable() {
            @Override
            public void run() {
                for(DownloadObserver observer : observerList){
                    observer.onDownloadProgressChange(downloadInfo);
                }
            }
        });

    }

    /**
     * 暂停的方法
     */
    public void pause(AppInfo appInfo){
        //找到downloadInfo，将其状态更改为暂停
        DownloadInfo downloadInfo = downloadInfoMap.get(appInfo.getId());
        if(downloadInfo!=null){
            //将状态设置为暂停
            downloadInfo.setState(STATE_PAUSE);
            notifyDownloadStateChange(downloadInfo);
        }
    }

    /**
     * 安装apk的方法
     */
    public void installApk(AppInfo appInfo){
        DownloadInfo downloadInfo = getDownloadInfo(appInfo);
        if(downloadInfo!=null){
            //发送Intent，启动PackageInstaller
        /*<action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="content" />
        <data android:scheme="file" />
        <data android:mimeType="application/vnd.android.package-archive" />*/

            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setDataAndType(Uri.parse("file://"+downloadInfo.getPath()),"application/vnd.android.package-archive");
            GooglePlayApp.context.startActivity(intent);
        }
    }

    public DownloadInfo getDownloadInfo(AppInfo appInfo){
        return downloadInfoMap.get(appInfo.getId());
    }

    /**
     * 注册下载观察者对象
     * @param observer
     */
    public void registerDownloadObserver(DownloadObserver observer){
        if(!observerList.contains(observer)){
            observerList.add(observer);
        }
    }

    /**
     * 移除下载观察者对象
     * @param observer
     */
    public void unregisterDownloadObserver(DownloadObserver observer){
        if(observerList.contains(observer)){
            observerList.remove(observer);
        }
    }



    //定义下载监听器
    public interface DownloadObserver{
        /**
         * 下载进度更新的回调方法
         */
        void onDownloadProgressChange(DownloadInfo downloadInfo);

        /**
         * 下载状态改变的回调方法
         */
        void onDownloadStateChange(DownloadInfo downloadInfo);
    }

}
